/**
 * @file       ili9225g.c
 * @author     wangbing
 * @email      mz8023yt@163.com
 * @version    V1.0
 * @date       2022-03-08
 * @brief      ips lcd panel drvier
 */

#include "ili9225g.h"
#include <string.h>

void ili9225g_init(struct ili9225g* lcd)
{
	/* reset sequence */
	/* the spec requires at least 10us */
	lcd->ops.reset(LOW);
	lcd->ops.msleep(100);

	/* the spec requires a maximum wait of 120ms */
	lcd->ops.reset(HIGH);
	lcd->ops.msleep(50);

	/* initializing the lcd */
	// LCD Init For 2.2inch LCD Panel with ILI9225.
	lcd->ops.i80_reg_write(0x10, 0x0000); // Set SAP,DSTB,STB
	lcd->ops.i80_reg_write(0x11, 0x0000); // Set APON,PON,AON,VCI1EN,VC
	lcd->ops.i80_reg_write(0x12, 0x0000); // Set BT,DC1,DC2,DC3
	lcd->ops.i80_reg_write(0x13, 0x0000); // Set GVDD
	lcd->ops.i80_reg_write(0x14, 0x0000); // Set VCOMH/VCOML voltage
	lcd->ops.msleep(40);                  // Delay 40 ms

	// Please follow this power on sequence
	lcd->ops.i80_reg_write(0x11, 0x0018); // Set APON,PON,AON,VCI1EN,VC
	lcd->ops.i80_reg_write(0x12, 0x1121); // Set BT,DC1,DC2,DC3
	lcd->ops.i80_reg_write(0x13, 0x0063); // Set GVDD
	lcd->ops.i80_reg_write(0x14, 0x3961); // Set VCOMH/VCOML voltage
	lcd->ops.i80_reg_write(0x10, 0x0800); // Set SAP,DSTB,STB
	lcd->ops.msleep(10);                  // Delay 10 ms
	lcd->ops.i80_reg_write(0x11, 0x1038); // Set APON,PON,AON,VCI1EN,VC
	lcd->ops.msleep(30);                  // Delay 30 ms
	lcd->ops.i80_reg_write(0x02, 0x0100); // set 1 line inversion

	lcd->ops.i80_reg_write(0x01, 0x011C); // set the display line number and display direction
	lcd->ops.i80_reg_write(0x03, 0x1030); // set GRAM i80_reg_write direction.

	lcd->ops.i80_reg_write(0x07, 0x0000); // Display off
	lcd->ops.i80_reg_write(0x08, 0x0808); // set the back porch and front porch
	lcd->ops.i80_reg_write(0x0B, 0x1100); // set the clocks number per line
	lcd->ops.i80_reg_write(0x0C, 0x0000); // CPU interface
	lcd->ops.i80_reg_write(0x0F, 0x0501); // Set Osc
	lcd->ops.i80_reg_write(0x15, 0x0020); // Set VCI recycling
	lcd->ops.i80_reg_write(0x20, 0x0000); // RAM Address
	lcd->ops.i80_reg_write(0x21, 0x0000); // RAM Address

	/* Set GRAM area */
	lcd->ops.i80_reg_write(0x30, 0x0000);
	lcd->ops.i80_reg_write(0x31, 0x00DB);
	lcd->ops.i80_reg_write(0x32, 0x0000);
	lcd->ops.i80_reg_write(0x33, 0x0000);
	lcd->ops.i80_reg_write(0x34, 0x00DB);
	lcd->ops.i80_reg_write(0x35, 0x0000);
	lcd->ops.i80_reg_write(0x36, 0x00AF);
	lcd->ops.i80_reg_write(0x37, 0x0000);
	lcd->ops.i80_reg_write(0x38, 0x00DB);
	lcd->ops.i80_reg_write(0x39, 0x0000);

	/* Adjust the Gamma 2.2 Curve */
	lcd->ops.i80_reg_write(0x50, 0x0603);
	lcd->ops.i80_reg_write(0x51, 0x080D);
	lcd->ops.i80_reg_write(0x52, 0x0D0C);
	lcd->ops.i80_reg_write(0x53, 0x0205);
	lcd->ops.i80_reg_write(0x54, 0x040A);
	lcd->ops.i80_reg_write(0x55, 0x0703);
	lcd->ops.i80_reg_write(0x56, 0x0300);
	lcd->ops.i80_reg_write(0x57, 0x0400);
	lcd->ops.i80_reg_write(0x58, 0x0B00);
	lcd->ops.i80_reg_write(0x59, 0x0017);

	lcd->ops.i80_reg_write(0x0F, 0x0701);
	lcd->ops.i80_reg_write(0x07, 0x0012);
	lcd->ops.msleep(50);
	lcd->ops.i80_reg_write(0x07, 0x1017);

	/* light up backlight */
	lcd->ops.backlight(HIGH);
}

void ili9225g_rect_fill(struct ili9225g* lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t* color)
{
	int len = 0;

	lcd->ops.i80_reg_write(0x36, x2);
	lcd->ops.i80_reg_write(0x37, x1);
	lcd->ops.i80_reg_write(0x38, y2);
	lcd->ops.i80_reg_write(0x39, y1);
	lcd->ops.i80_reg_write(0x20, x1);
	lcd->ops.i80_reg_write(0x21, y1);

	len = (x2 - x1 + 1) * (y2 - y1 + 1) * 2;
	lcd->ops.i80_color_write(0x22, color, len);
}
